package com.quectel.mobile.controller.propertybill;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.func.LambdaUtil;
import com.quectel.business.common.propertybill.PropertyBillBusiness;
import com.quectel.constant.core.household.HouseholdConstants;
import com.quectel.constant.core.invoice.InvoiceConstants;
import com.quectel.constant.core.propertybill.PropertyBillConstants;
import com.quectel.constant.global.SystemConstants;
import com.quectel.core.module.household.dto.HouseholdRoomDto;
import com.quectel.core.module.household.service.HouseholdRoomService;
import com.quectel.core.module.propertybill.dto.PropertyBillDto;
import com.quectel.core.module.propertybill.service.PropertyBillService;
import com.quectel.core.module.propertybill.vo.PropertyBillAmountVo;
import com.quectel.mobile.controller.BaseController;
import com.quectel.mobile.util.SessionHolder;
import com.quectel.util.common.DateUtils;
import com.quectel.util.common.Page;
import com.quectel.util.common.Request;
import com.quectel.util.common.Response;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangheng
 * @email nolan.zhang@quectel.com
 * @date 2023/4/19 14:16
 * @description new java file header...
 */
@RestController
@RequestMapping("propertyBill")
@Tag(name = "PropertyBillController", description = "物业账单相关api")
public class PropertyBillController extends BaseController {


    public static final String NOT_PAY_FLAG = "1";
    public static final String PAID_FLAG = "2";

    @DubboReference
    private PropertyBillService propertyBillService;
    @DubboReference
    private HouseholdRoomService householdRoomService;

    @Autowired
    private PropertyBillBusiness propertyBillBusiness;

    @GetMapping("queryList")
    @Operation(summary = "根据条件查询账单列表")
    public Response<Page<PropertyBillDto>> queryList(
            @Parameter(description = "从1开始的页码数") @RequestParam Integer pageNo,
            @Parameter(description = "每页多少条") @RequestParam Integer pageSize,
            @Parameter(description = "查询flag,1:待缴账单,2:已缴账单") @RequestParam String queryFlag,
            @Parameter(description = "账单开始时间,示例2023-01") @RequestParam(required = false) String startDateFlag,
            @Parameter(description = "过滤开票条件,0未开票订单") @RequestParam(required = false) Byte invoiceCondition,
            @Parameter(description = "过滤房间") @RequestParam(required = false) Long roomId
    ) {

        Request request = Request.configParams(Request.parseParams(httpServletRequest));

        if (SessionHolder.getLoginMobileUserSession() == null ||
                SessionHolder.getLoginMobileUserSession().getCurrentHousehold() == null) {
            return Response.<Page<PropertyBillDto>>ok().wrap(Page.empty(request.getPageNo(), request.getPageSize()));
        }

        request.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getTenantId());
        request.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getVillageId());
        //查询认证房屋列表
        List<HouseholdRoomDto> householdRoomDtos = householdRoomService.selectByHouseholdId(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getId());
        //过滤 必须时候业主或者家人
        Set<Long> collect = householdRoomDtos.stream()
                .filter(householdRoomDto -> HouseholdConstants.IDENTITY_CATEGORY_OWNER.equals(householdRoomDto.getIdentityCategory())
                        || HouseholdConstants.IDENTITY_CATEGORY_FAMILY.equals(householdRoomDto.getIdentityCategory()))
                .map(HouseholdRoomDto::getRoomId).collect(Collectors.toSet());

        if (CollectionUtils.isEmpty(collect)) {
            return Response.<Page<PropertyBillDto>>ok().wrap(Page.empty(request.getPageNo(), request.getPageSize()));
        }

        request.put(PropertyBillConstants.ROOM_IDS, collect);
        if (NOT_PAY_FLAG.equals(queryFlag)) {
            //未缴费账单
            request.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.NOT_PAY_STATUS_LIST);
            //未缴费账单按账单生成时间倒序
            request.put(SystemConstants.SORT_ORDER_BY_KEY, PropertyBillConstants.CREATE_TIME_ORDER_KEY);
            request.put(SystemConstants.SORT_ORDER_RULE_KEY, SystemConstants.SORT_ORDER_RULE_DESC);
        } else if (PAID_FLAG.equals(queryFlag)) {
            //缴费账单
            request.put(SystemConstants.PAY_STATUSES, PropertyBillConstants.PAID_STATUS_LIST);
            //缴费账单按支付时间倒序
            request.put(SystemConstants.SORT_ORDER_BY_KEY, PropertyBillConstants.PAY_TIME_ORDER_KEY);
            request.put(SystemConstants.SORT_ORDER_RULE_KEY, SystemConstants.SORT_ORDER_RULE_DESC);
        }

        //未开票订单过滤
        if (InvoiceConstants.InvoiceStatus.NOT_SUBMITTED.getType().equals(invoiceCondition)) {
            request.put(LambdaUtil.getFieldName(PropertyBillDto::getInvoiceStatus), String.valueOf(InvoiceConstants.InvoiceStatus.NOT_SUBMITTED.getType()));
        }
        //日期过滤 账单开始时间查询
        if (StringUtils.isNotBlank(startDateFlag)) {
            Date date = DateUtils.parse(startDateFlag, DateUtils.FormatType.MONTH);
            DateTime startDateMonthBegin = DateUtil.beginOfMonth(date);
            DateTime startDateMonthEnd = DateUtil.endOfMonth(date);
            request.put(PropertyBillConstants.START_DATE_SLOT_KEY_PAIR.getLeft(), DateUtils.format(startDateMonthBegin, DateUtils.FormatType.SIMPLE));
            request.put(PropertyBillConstants.START_DATE_SLOT_KEY_PAIR.getRight(), DateUtils.format(startDateMonthEnd, DateUtils.FormatType.SIMPLE));
        }
        request.put(PropertyBillConstants.START_DATE_FLAG, startDateFlag);

        //查询账单
        int total = propertyBillService.queryTotal(request.getParams());
        List<PropertyBillDto> result;
        if (total > 0) {
            result = propertyBillService.queryList(request.getParams());

            //未缴费账单计算滞纳金和优惠活动
            if (NOT_PAY_FLAG.equals(queryFlag)) {
                result.forEach(propertyBillDto -> {
                    PropertyBillAmountVo propertyBillAmountVo = propertyBillBusiness.generatePropertyBill(propertyBillDto.getChargeableListId(), propertyBillDto.getRoomId(), propertyBillDto.getStartDate(), Boolean.TRUE);
                    PropertyBillDto editBillDto = propertyBillBusiness.genBillByPropertyBillAmountVo(propertyBillAmountVo);
                    //更新PropertyBill
                    propertyBillDto.setTotalAmount(editBillDto.getTotalAmount());
                    propertyBillDto.setItemAmount(editBillDto.getItemAmount());
                    propertyBillDto.setDiscountAmount(editBillDto.getDiscountAmount());
                    propertyBillDto.setOverdueAmount(editBillDto.getOverdueAmount());
                    propertyBillDto.setOverdueDate(editBillDto.getOverdueDate());
                    propertyBillDto.setOverdueDays(editBillDto.getOverdueDays());
                    propertyBillDto.setStartDate(editBillDto.getStartDate());
                    propertyBillDto.setEndDate(editBillDto.getEndDate());
                    //是否参加了活动
                    if (propertyBillAmountVo.getPropertyChargeableListActivity() != null) {
                        propertyBillDto.setActivityFlag(SystemConstants.NORMAL);
                    } else {
                        propertyBillDto.setActivityFlag(SystemConstants.ABNORMAL);
                    }
                });
            }

        } else {
            result = new ArrayList<>();
        }
        Page<PropertyBillDto> page = new Page<>(request.getPageNo(), request.getPageSize(), total, result);
        return Response.<Page<PropertyBillDto>>ok().wrap(page);
    }


    /**
     * 查看账单详情
     *
     * @param id
     * @return
     */
    @GetMapping("info/{id}")
    @Operation(summary = "查询单条记录")
    public Response<PropertyBillDto> info(@PathVariable("id") Long id) {
        Map<String, Object> params = new HashMap<>();

        params.put(SystemConstants.ENTITY_ID_FLAG, String.valueOf(id));

        params.put(LambdaUtil.getFieldName(PropertyBillDto::getTenantId), SessionHolder.getLoginMobileUserSession().getTenantId());
        params.put(LambdaUtil.getFieldName(PropertyBillDto::getVillageId), SessionHolder.getLoginMobileUserSession().getCurrentVillageId());
        //查询认证房屋列表
        List<HouseholdRoomDto> householdRoomDtos = householdRoomService.selectByHouseholdId(SessionHolder.getLoginMobileUserSession().getCurrentHousehold().getId());
        //过滤 必须时候业主或者家人
        Set<Long> collect = householdRoomDtos.stream()
                .filter(householdRoomDto -> HouseholdConstants.IDENTITY_CATEGORY_OWNER.equals(householdRoomDto.getIdentityCategory())
                        || HouseholdConstants.IDENTITY_CATEGORY_FAMILY.equals(householdRoomDto.getIdentityCategory()))
                .map(HouseholdRoomDto::getRoomId).collect(Collectors.toSet());
        params.put(PropertyBillConstants.ROOM_IDS, collect);

        if (CollectionUtils.isEmpty(collect)) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        if (propertyBillService.queryTotal(params) <= 0) {
            return Response.error(SystemConstants.ILLEGAL_MSG);
        }

        PropertyBillDto propertyBillDto = propertyBillService.selectById(id);
        //返回已经保存的账单详情
        if (propertyBillDto.getPropertyBillAmount() != null) {
            return Response.<PropertyBillDto>ok().wrap(propertyBillDto);
        } else {
            PropertyBillAmountVo propertyBillAmountVo = propertyBillBusiness.generatePropertyBill(propertyBillDto.getChargeableListId(), propertyBillDto.getRoomId(), propertyBillDto.getStartDate(), Boolean.TRUE);
            //不用重复设置
            propertyBillAmountVo.setVillageRoom(null);
            propertyBillDto.setPropertyBillAmount(propertyBillAmountVo);

        }
        return Response.<PropertyBillDto>ok().wrap(propertyBillDto);
    }

}
